package de.g18.it0a.jlaser.domain;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import de.g18.it0a.jlaser.exception.InitializationException;


public final class RoomConfiguration {

    private final int width;
    private final int height;

    private final int tileWidth;
    private final int tileHeight;

    private final Position laserPosition;
    private final List<Position> vetrinePositions;

    private Set<Position> possibleMirrorPositions;
    
    


    public RoomConfiguration(int aWidth, int aHeight) throws InitializationException {
        this(aWidth, aHeight, new ArrayList<Position>());
    }

    public RoomConfiguration(int aWidth, int aHeight, List<Position> aVetrinePositions) throws InitializationException {
        this(aWidth, aHeight, new Position(0, 0), aVetrinePositions);
    }

    public RoomConfiguration(int aWidth, int aHeight, Position aLaserPosition, List<Position> aVetrinePositions)  throws InitializationException {
        this(aWidth, aHeight, 100, 100, aLaserPosition, aVetrinePositions);
    }

    public RoomConfiguration(int aWidth, int aHeight, int aTileWidht, int aTileHeight,
                             Position aLaserPosition)  throws InitializationException {
        this(aWidth, aHeight, aTileWidht, aTileHeight, aLaserPosition, new ArrayList<Position>());
    }

    public RoomConfiguration(int aWidth, int aHeight, int aTileWidht, int aTileHeight,
                             Position aLaserPosition, List<Position> aVetrinePositions) throws InitializationException {
        width = aWidth;
        height = aHeight;
        tileWidth = aTileWidht;
        tileHeight = aTileHeight;
        ensureValidDimension();

        laserPosition = aLaserPosition;
        vetrinePositions = aVetrinePositions;
        possibleMirrorPositions = new HashSet<Position>();
        fillPossibleMirrorPositions();
    }

    private void ensureValidDimension() throws InitializationException {
        if (getWidth() % tileWidth != 0) {
            throw new InitializationException("Width must be a multiple of " + tileWidth);
        }
        if (getHeight() % tileHeight != 0) {
            throw new InitializationException("Height must be a multiple of " + tileHeight);
        }
    }
    
    public boolean isValidTilePosition(Position aPosition) {
    	return aPosition.getX() % getTileWidth() == 0
    			&& aPosition.getX() >= 0
    			&& aPosition.getX() <= getWidth()
    			&& aPosition.getY() % getTileHeight() == 0
    			&& aPosition.getY() <= getHeight()
    			&& aPosition.getY() >= 0;
    }

    private void fillPossibleMirrorPositions() {
        if (!possibleMirrorPositions.isEmpty()) {
            return;
        }

        for (int i = 0; i <= getHeight(); i += tileHeight) {
            possibleMirrorPositions.add(new Position(0, i));
            possibleMirrorPositions.add(new Position(getWidth(), i));
        }

        for (int i = 0; i <= getWidth(); i += tileWidth) {
            possibleMirrorPositions.add(new Position(i, 0));
            possibleMirrorPositions.add(new Position(i, getHeight()));
        }
        possibleMirrorPositions.remove(laserPosition);
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }
    
    public String getWidthDouble() {
    	DecimalFormat f = new DecimalFormat("#0.00"); 
    	double temp = width;
    	return f.format(temp);
    }
    
    public String getHeightDouble() {
    	DecimalFormat f = new DecimalFormat("#0.00"); 
    	double temp = height;
    	return f.format(temp);
    }

    public int getTileWidth() {
        return tileWidth;
    }

    public int getTileHeight() {
        return tileHeight;
    }

    public Position getLaserPosition() {
        return laserPosition;
    }

    public List<Position> getVetrinePositions() {
        return vetrinePositions;
    }

    public Vector<Position> getPossibleMirrorPositions() {
        return new Vector<Position>(possibleMirrorPositions);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + height;
        result = prime * result + (laserPosition == null ? 0 : laserPosition.hashCode());
        result = prime * result + (possibleMirrorPositions == null ? 0 : possibleMirrorPositions.hashCode());
        result = prime * result + tileHeight;
        result = prime * result + tileWidth;
        result = prime * result + (vetrinePositions == null ? 0 : vetrinePositions.hashCode());
        result = prime * result + width;
        return result;
    }

    @Override
    public boolean equals(Object aObject) {
        if (aObject == this) {
            return true;
        }
        if (aObject == null) {
            return false;
        }
        if (!(aObject instanceof RoomConfiguration)) {
            return false;
        }

        RoomConfiguration other = (RoomConfiguration) aObject;
        return getWidth() == other.getWidth()
                && getHeight() == other.getHeight()
                && getTileWidth() == other.getTileWidth()
                && getTileHeight() == other.getTileHeight()
                && getLaserPosition().equals(other.getLaserPosition())
                && getVetrinePositions().equals(other.getVetrinePositions());
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "[width=" + getWidth()
                                          + ",height=" + getHeight()
                                          + ",tileWidth=" + getTileWidth()
                                          + ",tileHeight=" + getTileHeight()
                                          + ",laserPosition=" + getLaserPosition()
                                          + ",vetrines=" + getVetrinePositions().size() + "]";
    }
}
